/**
 * 数据字典页面
 */
import { FC, useEffect, useState } from "react";
import { observer, inject } from "mobx-react";
import {
  Row,
  Col,
  Button,
  Modal,
  Form,
  Input,
  message,
  Table,
  Space,
  Popconfirm,
  Typography,
  Drawer,
  Descriptions,
  Tooltip,
} from "antd";

import {
  EditOutlined,
  DeleteOutlined,
  PlusOutlined,
  EyeOutlined,
  CaretUpOutlined,
  CaretDownOutlined,
} from "@ant-design/icons";
import { ITStore } from "../../store";
import { ITColumns, ITDictValue } from "../../store/interfaces";

const { Link } = Typography;

type TProp = {
  store: ITStore;
};

const layout = {
  labelCol: { span: 6 },
  wrapperCol: { span: 16 },
};

interface ITLangDict {
  id?: string;
  key: string;
  desc: string;
}

// 字典值弹窗
const DictValueModal: FC<TProp | any> = inject("store")(
  observer(({ store }: TProp) => {
    const {
      languageStore: { lang },
      dictionaryStore: {
        showValueModal,
        changeShowValueModal,
        detailLabelData,
        addDictValue,
        addDictValueLoading,
        dictValues,
        getDictValue,
        valueModalData,
        changeValueModalData,
        updateDictValue,
        getFullDict,
      },
    } = store;

    const [form] = Form.useForm();

    useEffect(() => {
      if (valueModalData) {
        form.setFieldsValue({
          ...valueModalData,
        });
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [valueModalData]);

    const closeModal = () => {
      form.resetFields();
      changeValueModalData(null);
      changeShowValueModal(false);
    };

    const formFinish = async (values: ITDictValue) => {
      const { id } = values;
      if (detailLabelData) {
        values.pid = detailLabelData.id;
      }
      let res = null;
      let msg: string = "";
      if (id) {
        if (valueModalData) {
          values.sort = valueModalData?.sort;
        }
        res = await updateDictValue(values);
        msg = lang["langmodifysuccess"];
      } else {
        values.sort = dictValues.length;
        res = await addDictValue(values);
        msg = lang["langaddsuccess"];
      }
      if (!res) {
        closeModal();
        getFullDict(true);
        getDictValue({ id: detailLabelData?.id });
        message.success(msg);
      } else {
        const { msg } = res;
        message.error(msg);
      }
    };

    return (
      <Modal
        getContainer={false}
        title={lang["langadddictvalue"]}
        open={showValueModal}
        onOk={() => {
          form.submit();
        }}
        onCancel={closeModal}
        confirmLoading={addDictValueLoading}
        forceRender
        zIndex={1001}
      >
        <Form {...layout} form={form} name="dictForm" onFinish={formFinish}>
          <Form.Item name="id" label="" hidden={true}>
            <Input />
          </Form.Item>
          <Form.Item name="pid" label="" hidden={true}>
            <Input />
          </Form.Item>
          <Form.Item
            name="label"
            label={lang["langlabel"]}
            rules={[{ required: true }]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            name="cnlabel"
            label={lang["langcnlabel"]}
            rules={[{ required: true }]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            name="value"
            label={lang["langvalue"]}
            rules={[{ required: true }]}
          >
            <Input />
          </Form.Item>
          <Form.Item name="desc" label={lang["langdescription"]}>
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    );
  })
);

// 新增编辑 字典label弹窗
const DictLabelModal: FC<TProp | any> = inject("store")(
  observer(({ store }: TProp) => {
    const {
      languageStore: { lang },
      dictionaryStore: {
        editDictLabelData,
        showAddEditLabelModal,
        changeShowAddEditLabelModal,
        addDictLabel,
        getAllDictLabel,
        updateDictLabel,
        showAddLabelLoading,
      },
    } = store;

    const [form] = Form.useForm();

    useEffect(() => {
      if (editDictLabelData) {
        form.setFieldsValue({
          ...editDictLabelData,
        });
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [editDictLabelData]);

    // 关闭弹窗
    const closeModal = () => {
      changeShowAddEditLabelModal(false);
    };

    const formFinish = async (values: ITLangDict) => {
      let res = null;
      let msg: string = "";
      if (!!editDictLabelData) {
        // 编辑
        res = await updateDictLabel(values);
        msg = lang["langmodifysuccess"];
      } else {
        // 新增
        res = await addDictLabel(values);
        msg = lang["langaddsuccess"];
      }
      if (!res) {
        closeModal();
        getAllDictLabel();
        message.success(msg);
      } else {
        const { msg } = res;
        message.error(msg);
      }
    };

    return (
      <Modal
        title={
          !!editDictLabelData
            ? lang["langdictedittitle"]
            : lang["langdictaddtitle"]
        }
        open={showAddEditLabelModal}
        destroyOnClose={true}
        onOk={() => {
          form.submit();
        }}
        onCancel={closeModal}
        confirmLoading={showAddLabelLoading}
      >
        <Form {...layout} form={form} name="dictForm" onFinish={formFinish}>
          <Form.Item name="id" label="" hidden={true}>
            <Input />
          </Form.Item>
          <Form.Item
            name="key"
            label={lang["langkeyword"]}
            rules={[{ required: true }]}
          >
            <Input disabled={!!editDictLabelData} />
          </Form.Item>
          <Form.Item name="desc" label={lang["langdescription"]}>
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    );
  })
);

// 搜索和新增按钮组件
const SearchAddComp: FC<TProp | any> = inject("store")(
  observer(({ store }: TProp) => {
    const {
      languageStore: { lang },
      dictionaryStore: { changeShowAddEditLabelModal },
    } = store;

    // const [form] = Form.useForm();

    const handleClickAdd = () => {
      changeShowAddEditLabelModal(true);
    };

    return (
      <Row style={{ marginBottom: 20 }}>
        <Col span={20}></Col>
        <Col span={4}>
          <Button
            type="primary"
            icon={<PlusOutlined />}
            style={{ float: "right" }}
            onClick={handleClickAdd}
          >
            {lang["langbuttonadd"]}
          </Button>
        </Col>
      </Row>
    );
  })
);

// 字典label列表
const DictLabelList: FC<TProp | any> = inject("store")(
  observer(({ store }: TProp) => {
    const {
      languageStore: { lang },
      dictionaryStore: {
        getAllDictLabel,
        allDictLabelLoading,
        delLabelLoading,
        allDictLabel,
        deleteDictLabel,
        changeEditDictLabelData,
        changeShowAddEditLabelModal,
        changeShowDetail,
        changeDetailLabelData,
        getDictValue,
      },
    } = store;

    const [delData, setDelData] = useState<ITLangDict | null>(null);

    useEffect(() => {
      getAllDictLabel();
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const modifyItem = (data: any) => {
      changeEditDictLabelData(data);
      changeShowAddEditLabelModal(true);
    };

    const deleteItem = async (data: any) => {
      // 判断是否有值，否则提示先清空值
      const list: any = await getDictValue({ id: data.id });
      if (list && list.length) {
        message.error(lang["langemptyvalue"]);
      } else {
        setDelData(data);
        const { id } = data;
        const res = await deleteDictLabel({ id });
        if (!res) {
          getAllDictLabel();
          message.success(lang["langdeletesuccess"]);
          setDelData(null);
        }
      }
    };

    const showDetail = (data: ITLangDict) => {
      changeDetailLabelData(data);
      changeShowDetail(true);
    };

    const columns: ITColumns[] = [
      {
        title: lang["langkeyword"],
        dataIndex: "key",
        key: "key",
        render: (text: string, record: ITLangDict) => (
          <Link
            onClick={() => {
              showDetail(record);
            }}
          >
            {text}
          </Link>
        ),
      },
      {
        title: lang["langdescription"],
        dataIndex: "desc",
        key: "desc",
      },
      {
        title: lang["langedit"],
        dataIndex: "edit",
        key: "edit",
        width: 110,
        align: "center",
        render: (_: string, record: ITLangDict) => {
          return (
            <Space>
              <Tooltip title={lang["langview"]}>
                <Button
                  type="link"
                  icon={<EyeOutlined />}
                  onClick={() => {
                    showDetail(record);
                  }}
                />
              </Tooltip>
              <Tooltip title={lang["langedit"]}>
                <Button
                  type="link"
                  icon={<EditOutlined />}
                  onClick={() => {
                    modifyItem(record);
                  }}
                />
              </Tooltip>
              <Popconfirm
                title={lang["langconfirmdel"]}
                onConfirm={() => {
                  deleteItem(record);
                }}
              >
                <Tooltip title={lang["langdelete"]}>
                  <Button
                    type="link"
                    danger
                    loading={delData?.id === record.id && delLabelLoading}
                    icon={<DeleteOutlined />}
                  />
                </Tooltip>
              </Popconfirm>
            </Space>
          );
        },
      },
    ];

    return (
      <Table
        dataSource={allDictLabel}
        columns={columns}
        bordered
        loading={allDictLabelLoading}
      />
    );
  })
);

// 字典详情
const DictDetail: FC<TProp | any> = inject("store")(
  observer(({ store }: TProp) => {
    const {
      dictionaryStore: {
        showDetail,
        detailLabelData,
        changeShowDetail,
        changeDetailLabelData,
        changeShowValueModal,
        getDictValue,
        dictValues,
        changeDictValues,
        delValueLoading,
        delValue,
        changeValueModalData,
        getDictValueLoading,
        updateDictValue,
      },
      languageStore: { lang },
    } = store;

    const [delData, setDelData] = useState<ITDictValue | null>(null);

    useEffect(() => {
      if (detailLabelData) {
        getDictValue({ id: detailLabelData.id });
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [detailLabelData]);

    const close = () => {
      changeShowDetail(false);
      changeDetailLabelData(null);
      changeDictValues([]);
    };

    const showDictValueModal = () => {
      changeShowValueModal(true);
    };

    const modifyItem = (data: ITDictValue) => {
      changeValueModalData(data);
      changeShowValueModal(true);
    };

    const deleteItem = async (data: ITDictValue) => {
      setDelData(data);
      const { id } = data;
      const res = await delValue({ id });
      if (!res) {
        getDictValue({ id: detailLabelData?.id });
        message.success(lang["langdeletesuccess"]);
        setDelData(null);
      }
    };

    // 提升排序
    const upItem = async (data: ITDictValue) => {
      const { key } = data;
      const nextKey = key - 1;
      let nextItem: any = {};
      dictValues.some((item: ITDictValue) => {
        if (item.key === nextKey) {
          nextItem = item;
          return true;
        }
        return false;
      });
      await updateDictValue({
        ...data,
        sort: data.sort - 1,
      });
      await updateDictValue({
        ...nextItem,
        sort: nextItem.sort + 1,
      });
      getDictValue({ id: detailLabelData?.id });
      message.success(lang["langmodifysuccess"]);
    };

    // 降低排序
    const downItem = async (data: ITDictValue) => {
      const { key } = data;
      const nextKey = key + 1;
      let nextItem: any = {};
      dictValues.some((item: ITDictValue) => {
        if (item.key === nextKey) {
          nextItem = item;
          return true;
        }
        return false;
      });
      await updateDictValue({
        ...data,
        sort: data.sort + 1,
      });
      await updateDictValue({
        ...nextItem,
        sort: nextItem.sort - 1,
      });
      getDictValue({ id: detailLabelData?.id });
      message.success(lang["langmodifysuccess"]);
    };

    const columns: ITColumns[] = [
      {
        title: lang["langlabel"],
        dataIndex: "label",
        key: "label",
      },
      {
        title: lang["langcnlabel"],
        dataIndex: "cnlabel",
        key: "cnlabel",
      },
      {
        title: lang["langvalue"],
        dataIndex: "value",
        key: "value",
      },
      {
        title: lang["langdescription"],
        dataIndex: "desc",
        key: "desc",
      },
      {
        title: lang["langedit"],
        dataIndex: "edit",
        key: "edit",
        width: 65,
        render: (_: string, record: ITDictValue) => {
          return (
            <Space>
              <Button
                type="link"
                icon={<EditOutlined />}
                onClick={() => {
                  modifyItem(record);
                }}
              />
              <Popconfirm
                title={lang["langconfirmdel"]}
                onConfirm={() => {
                  deleteItem(record);
                }}
              >
                <Button
                  type="link"
                  danger
                  loading={delData?.id === record.id && delValueLoading}
                  icon={<DeleteOutlined />}
                />
              </Popconfirm>
              {record.sort !== 0 && (
                <Button
                  type="link"
                  icon={<CaretUpOutlined />}
                  onClick={() => {
                    upItem(record);
                  }}
                />
              )}
              {!!dictValues && record.sort !== dictValues.length - 1 && (
                <Button
                  type="link"
                  icon={<CaretDownOutlined />}
                  onClick={() => {
                    downItem(record);
                  }}
                />
              )}
            </Space>
          );
        },
      },
    ];

    return (
      <Drawer
        title=""
        placement="right"
        onClose={close}
        open={showDetail}
        closable={false}
        width="50%"
        footer={
          <Row>
            <Col>
              <Button type="primary" onClick={close}>
                {lang["langclose"]}
              </Button>
            </Col>
          </Row>
        }
      >
        <Descriptions bordered layout="vertical">
          <Descriptions.Item label={lang["langkeyword"]}>
            {detailLabelData?.key}
          </Descriptions.Item>
          <Descriptions.Item label={lang["langdescription"]}>
            {detailLabelData?.desc}
          </Descriptions.Item>
        </Descriptions>
        <Row style={{ marginTop: 20 }}>
          <Col span={24}>
            <Button
              type="primary"
              onClick={showDictValueModal}
              style={{ float: "right" }}
            >
              {lang["langadddictvalue"]}
            </Button>
          </Col>
        </Row>

        <Table
          dataSource={dictValues}
          columns={columns}
          bordered
          style={{ marginTop: 20 }}
          loading={getDictValueLoading}
        />
      </Drawer>
    );
  })
);

const Dictionary: FC<TProp | any> = ({ store }: TProp): JSX.Element => {
  return (
    <>
      {/* 搜索和新增按钮组件 */}
      <SearchAddComp />

      {/* 列表数据 */}
      <DictLabelList />

      {/* 新增字典弹窗 */}
      <DictLabelModal />

      {/* 字典详情 */}
      <DictDetail />

      {/* 字典值弹窗 */}
      <DictValueModal />
    </>
  );
};

export default inject("store")(observer(Dictionary));
